package com.ylz.sjzx.sio.core.group.manager;


import com.alibaba.boot.nacos.discovery.properties.NacosDiscoveryProperties;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.ylz.sjzx.sio.common.core.constant.Const;
import com.ylz.sjzx.sio.core.group.model.RpcProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务发现管理者
 *
 * @author
 * @version 1.0
 * @date 2021/1/7
 */
@Component
@Slf4j
public class DiscoverManager {

    public static NamingService namingService;


    public static GroupRpc rpcService;

    public DiscoverManager(@Autowired NacosDiscoveryProperties discoveryProperties
            , @Autowired GroupRpc rpcService) {
        try {
            namingService = NamingFactory.createNamingService(discoveryProperties.getServerAddr());
        } catch (NacosException e) {
            e.printStackTrace();
        }
        DiscoverManager.rpcService = rpcService;
        this.serviceFoundListen();
        //注册本机器service
        this.serviceRegister(DiscoverManager.rpcService.createLocalProperties());

    }

    public static void refreshService() {
        RpcProperties localProperties = rpcService.createLocalProperties();
        List<Instance> allInstances = new ArrayList<>(1);
        try {
            allInstances = namingService.getAllInstances(localProperties.getGroupName());
        } catch (NacosException e) {
            log.error("=========服务刷新失败======{}==", e);
        }
        DiscoverManager.refreshService(allInstances);
    }

    /**
     * 服务更新
     *
     * @param instances
     */
    public static void refreshService(List<Instance> instances) {
        instances.forEach(s -> {
            log.debug("=======监听到服务注册===={}==", s.toString());
            if (s.isHealthy()) {
                try {
                    DiscoverManager.rpcService.addRpcService(s);
                } catch (Exception e) {
                    log.error("=========注册服务失败======{}==", s.toString());
                    log.error(e.getMessage());
                }
            } else {
                try {
                    //不健康服务剔除
                    DiscoverManager.rpcService.removeRpcService(s.getIp(), s.getPort());
                } catch (Exception e) {
                    log.error("=========不健康服务注销失败======{}==", s.toString());
                    log.error(e.getMessage());
                }

            }

        });
    }

    /**
     * 服务发现监听
     */
    public void serviceFoundListen() {
        RpcProperties localProperties = rpcService.createLocalProperties();
        try {
            namingService.subscribe(localProperties.getGroupName(), new EventListener() {
                @Override
                public void onEvent(Event event) {
                    List<Instance> instances = ((NamingEvent) event).getInstances();
                    DiscoverManager.refreshService(instances);
                }
            });
        } catch (NacosException e) {
            log.error("=========添加nacos服务监听功能失败======{}==", e.getMessage());
        }
    }

    public void serviceRegister(RpcProperties remotingProperties) {
        try {
            Instance instance = new Instance();
            instance.setIp(remotingProperties.getIp());
            instance.setPort(remotingProperties.getPort());
            Map<String, String> otherData = new HashMap<String, String>();
            otherData.put(Const.GROUP_NAME, remotingProperties.getGroupName());
            otherData.put(Const.GROUP_ROLE, remotingProperties.getGroupRole());
            instance.setMetadata(otherData);
            // 即服务端6秒收不到客户端心跳，会将该客户端注册的实例设为不健康：
            namingService.registerInstance(remotingProperties.getGroupName(), instance);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
